﻿using amuudp;
using amuudp.package;
using fenping.package;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace amuudp
{
    public class SplitScreenServerEvents : IServerEvents
    {
        Form1 form;
        UdpServer receiver;
        int ServerId = 0;
        int ServerPort = 0;

        private delegate void progressCallbackDeleGate(object obj);

        public Dictionary<int, ClientInfo> Clients = new Dictionary<int, ClientInfo>();

        public SplitScreenServerEvents(int serverId, int ServerPort, Form1 form)
        {
            this.ServerId = serverId;
            this.ServerPort = ServerPort;
            this.receiver = new UdpServer(serverId, ServerPort, this);
            receiver.Start();
            this.form = form;
        }

        public void Connect(int clientId)
        {
            if(Clients.ContainsKey(clientId))
            {
                Connect(Clients[clientId].Ip, Clients[clientId].Port);
            }
            else
            {
                throw new Exception("客户端不存在");
            }
        }

        public void Connect(string ip, int port)
        {
            UdpInfo info = new UdpInfo("connect");
            info.Add("port", ServerPort.ToString());
            receiver.Send(info.ToString(), new IPEndPoint(IPAddress.Parse(ip), port));
        }

        public void ConnectReply(string ip, int port)
        {
            UdpInfo info = new UdpInfo("connected");
            receiver.Send(info.ToString(), new IPEndPoint(IPAddress.Parse(ip), port));
        }

        public void Capture(int clientId)
        {
            UdpInfo info = new UdpInfo("capture");
            SendMessage(info.ToString(), clientId);
        }

        public void StopCapture(int clientId)
        {
            UdpInfo info = new UdpInfo("stop");
            SendMessage(info.ToString(), clientId);
        }

        public void ClientSetting(int clientId, int frameRate, int width, int height)
        {
            UdpInfo info = new UdpInfo("setting");
            info.Add("framerate", frameRate.ToString());
            info.Add("width", width.ToString());
            info.Add("height", height.ToString());
            SendMessage(info.ToString(), clientId);
        }

        private void SendMessage(string message, int clientId)
        {
            if(Clients.ContainsKey(clientId))
            {
                receiver.Send(message, new IPEndPoint(IPAddress.Parse(Clients[clientId].Ip), Clients[clientId].Port));
            }
        }

        public void OnPackageComplete(Package package, IPAddress ip, int port, params object[] args)
        {
            if (package.Type == PackageType.Message)
            {
                MessagePackage messagePackage = new MessagePackage(package);
                UdpInfo info = new UdpInfo(messagePackage.Message);
                InfoRun(info, package.ClientId, ip);
            }
            else if (package.Type == PackageType.Image)
            {
                ImagePackage imagePackage = new ImagePackage(package);
                UpdateImage(package.ClientId, imagePackage);
            }
            else
            {
                Console.WriteLine($"非消息类型，客户端编号：{package.ClientId}，包ID：{package.Id}，包大小：{package.Size}, 包类型：{package.Type}");
            }
        }

        private void UpdateImage(int clientId, ImagePackage imagePackage)
        {
            if(!Clients.ContainsKey(clientId))
            {
                return;
            }

            if(imagePackage.Index > Clients[clientId].LastImageId)
            {
                this.form.UpdatePicture(clientId, imagePackage.BitMap);
                Clients[clientId].LastImageId = imagePackage.Index;
            }
        }

        private void InfoRun(UdpInfo info, int clientId, IPAddress ip)
        {
            if (info.Type == "connect")
            {
                ClientInfo client = new ClientInfo();
                client.Id = int.Parse(info.Get("clientid"));
                client.Port = int.Parse(info.Get("port"));
                client.Name = info.Get("clientname");
                client.Ip = ip.ToString();

                AddClient(client);
                // 收到客户端的连接，需要应答一下，客户端收到应答开始截图
                ConnectReply(client.Ip, client.Port);
            }
            else if(info.Type == "disconnect")
            {
                RemoveClient(clientId);
            }
            else
            {
                Log($"未处理的命令：{info.Type}");
            }
        }

        public void Log(string message)
        {
            form.Invoke(new progressCallbackDeleGate(form.Log), new object[] { message });
        }

        public void RemoveClient(int clientId)
        {
            if (Clients.ContainsKey(clientId))
            {
                Clients.Remove(clientId);
                UpdateClientViewList();
            }
        }

        public void AddClient(ClientInfo client)
        {
            if(Clients.ContainsKey(client.Id))
            {
                Log($"重复的客户端，ID：{client.Id}，名称：{client.Name}");
                return;
            }
            Clients.Add(client.Id, client);
            UpdateClientViewList();
        }

        private void UpdateClientViewList()
        {
            form.Invoke(new progressCallbackDeleGate(form.UpdateClientList), new object[] { Clients.Select(r => r.Value).ToList() });
        }

        public void OnReceive(Fragment fragment, IPAddress ip, int port, params object[] args)
        {

        }

        public void Stop()
        {
            receiver.Stop();
            foreach(int clientId in Clients.Keys)
            {
                StopCapture(clientId);
            }
        }
    }

    public class ClientInfo
    {
        public string Name;
        public int Id;
        public string Ip;
        public int Port;
        public int LastImageId = -1;
    }
}
